Micron Document
πŸŽ–οΈGitΠ―Ρ€Π°πŸŽ–οΈ

Node / meshtastic / Meshtastic-Android / files / .github / copilot-instructions.md

Displaying Rendered β€’ View raw β€’ Download

.github/copilot-instructions.md b4afe22030b1b47f9b48964696dcfc30373327c8 (b4afe220) Text, 13.86 KB

Meshtastic Android - Agent Guide

This file serves as a comprehensive guide for AI agents and developers working on the T383838Meshtastic-Android codebase. Use this as your primary reference for understanding the architecture, conventions, and strict rules of this project.

For execution-focused recipes, see T383838docs/agent-playbooks/README.md.

1. Project Vision & Architecture
Meshtastic-Android is a Kotlin Multiplatform (KMP) application for off-grid, decentralized mesh networks. The goal is to decouple business logic from the Android framework, enabling future expansion to iOS and other platforms while maintaining a high-performance native Android experience.

β€’ Language: Kotlin (primary), AIDL.
β€’ Build System: Gradle (Kotlin DSL). JDK 17 is REQUIRED.
β€’ Target SDK: API 36. Min SDK: API 26 (Android 8.0).
β€’ Flavors:
β€’ T383838fdroid: Open source only, no tracking/analytics.
β€’ T383838google: Includes Google Play Services (Maps) and DataDog analytics.
β€’ Core Architecture: Modern Android Development (MAD) with KMP core.
β€’ KMP Modules: Most T383838core:* modules. All declare T383838jvm(), T383838iosArm64(), and T383838iosSimulatorArm64() targets and compile clean across all.
β€’ Android-only Modules: T383838core:api (AIDL), T383838core:barcode (CameraX + flavor-specific decoder). Shared contracts abstracted into T383838core:ui/commonMain.
β€’ UI: Jetpack Compose Multiplatform (Material 3).
β€’ DI: Koin Annotations with K2 compiler plugin. Root graph assembly is centralized in T383838app and T383838desktop.
β€’ Navigation: JetBrains Navigation 3 (Stable Scene-based architecture) with shared backstack state.
β€’ Lifecycle: JetBrains multiplatform T383838lifecycle-viewmodel-compose and T383838lifecycle-runtime-compose.
β€’ Adaptive UI: Material 3 Adaptive (v1.3+) with support for Large (1200dp) and Extra-large (1600dp) breakpoints.
β€’ Database: Room KMP.

2. Codebase Map

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Directory β”‚ Description β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ T383838app/ β”‚ Main application module. Contains T383838MainActivity, Koin DI modules, and ap… β”‚
β”‚ T383838build-logic/ β”‚ Convention plugins for shared build configuration (e.g., T383838meshtastic.kmp… β”‚
β”‚ T383838config/ β”‚ Detekt static analysis rules (T383838config/detekt/detekt.yml) and Spotless fo… β”‚
β”‚ T383838docs/ β”‚ Architecture docs and agent playbooks. See T383838docs/agent-playbooks/README.… β”‚
β”‚ T383838core/model β”‚ Domain models and common data structures. β”‚
β”‚ T383838core:proto β”‚ Protobuf definitions (Git submodule). β”‚
β”‚ T383838core:common β”‚ Low-level utilities, I/O abstractions (Okio), and common types. β”‚
β”‚ T383838core:database β”‚ Room KMP database implementation. β”‚
β”‚ T383838core:datastore β”‚ Multiplatform DataStore for preferences. β”‚
β”‚ T383838core:repository β”‚ High-level domain interfaces (e.g., T383838NodeRepository, T383838LocationRepository). β”‚
β”‚ T383838core:domain β”‚ Pure KMP business logic and UseCases. β”‚
β”‚ T383838core:data β”‚ Core manager implementations and data orchestration. β”‚
β”‚ T383838core:network β”‚ KMP networking layer using Ktor, MQTT abstractions, and shared transpor… β”‚
β”‚ T383838core:di β”‚ Common DI qualifiers and dispatchers. β”‚
β”‚ T383838core:navigation β”‚ Shared navigation keys/routes for Navigation 3. β”‚
β”‚ T383838core:ui β”‚ Shared Compose UI components (T383838AlertHost, T383838SharedDialogs, T383838PlaceholderScre… β”‚
β”‚ T383838core:service β”‚ KMP service layer; Android bindings stay in T383838androidMain. β”‚
β”‚ T383838core:api β”‚ Public AIDL/API integration module for external clients. β”‚
β”‚ T383838core:prefs β”‚ KMP preferences layer built on DataStore abstractions. β”‚
β”‚ T383838core:barcode β”‚ Barcode scanning (Android-only). β”‚
β”‚ T383838core:nfc β”‚ NFC abstractions (KMP). Android NFC hardware implementation in T383838androidM… β”‚
β”‚ T383838core/ble/ β”‚ Bluetooth Low Energy stack using Kable. β”‚
β”‚ T383838core/resources/ β”‚ Centralized string and image resources (Compose Multiplatform). β”‚
β”‚ T383838core/testing/ β”‚ Shared test doubles, fakes, and utilities for T383838commonTest across all KMP… β”‚
β”‚ T383838feature/ β”‚ Feature modules (e.g., T383838settings, T383838map, T383838messaging, T383838node, T383838intro, T383838connectio… β”‚
β”‚ T383838desktop/ β”‚ Compose Desktop application β€” first non-Android KMP target. Thin host s… β”‚
β”‚ T383838mesh_service_example/ β”‚ Sample app showing T383838core:api service integration. β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

3. Development Guidelines & Coding Standards

A. UI Development (Jetpack Compose)
β€’ Material 3: The app uses Material 3.
β€’ Strings: MUST use the Compose Multiplatform Resource library in T383838core:resources (T383838stringResource(Res.string.your_key)). For ViewModels or non-composable Coroutines, use the asynchronous T383838getStringSuspend(Res.string.your_key). NEVER use hardcoded strings, and NEVER use the blocking T383838getString() in a coroutine.
β€’ Dialogs: Use centralized components in T383838core:ui (e.g., T383838MeshtasticResourceDialog).
β€’ Alerts: Use T383838AlertHost(alertManager) from T383838core:ui/commonMain in each platform host shell (T383838Main.kt, T383838DesktopMainScreen.kt). Do NOT duplicate inline alert-rendering boilerplate. For shared QR/contact dialogs, use the T383838SharedDialogs composable.
β€’ Placeholders: For desktop/JVM features not yet implemented, use T383838PlaceholderScreen(name) from T383838core:ui/commonMain. Do NOT define inline placeholder composables in feature modules.
β€’ Theme Picker: Use T383838ThemePickerDialog and T383838ThemeOption from T383838feature:settings/commonMain. Do NOT duplicate the theme dialog or enum in platform-specific source sets.
β€’ Adaptive Layouts: Use T383838currentWindowAdaptiveInfo(supportLargeAndXLargeWidth = true) to support the 2026 Desktop Experience breakpoints. Prioritize higher information density and mouse-precision interactions for Desktop and External Display (Android 16 QPR3) targets. Investigate 3-pane "Power User" scenes (e.g., Node List + Detail + Map/Charts) using Navigation 3 Scenes and T383838ThreePaneScaffold for widths β‰₯ 1200dp.
β€’ Platform/Flavor UI: Inject platform-specific behavior (e.g., map providers) via T383838CompositionLocal from T383838app.

B. Logic & Data Layer
β€’ KMP Focus: All business logic must reside in T383838commonMain of the respective T383838core module.
β€’ Platform purity: Never import T383838java.* or T383838android.* in T383838commonMain. Use KMP alternatives:
β€’ T383838java.util.Locale β†’ Kotlin T383838uppercase() / T383838lowercase() or T383838expect/T383838actual.
β€’ T383838java.util.concurrent.ConcurrentHashMap β†’ T383838atomicfu or T383838Mutex-guarded T383838mutableMapOf().
β€’ T383838java.util.concurrent.locks.* β†’ T383838kotlinx.coroutines.sync.Mutex.
β€’ T383838java.io.* β†’ Okio (T383838BufferedSource/T383838BufferedSink).
β€’ T383838kotlinx.coroutines.Dispatchers.IO β†’ T383838org.meshtastic.core.common.util.ioDispatcher (expect/actual).
β€’ Shared helpers over duplicated lambdas: When T383838androidMain and T383838jvmMain contain identical pure-Kotlin logic (formatting, action dispatch, validation), extract it to a function in T383838commonMain. Examples: T383838formatLogsTo() in T383838feature:settings, T383838handleNodeAction() in T383838feature:node, T383838findNodeByNameSuffix() in T383838feature:connections.
β€’ KMP file naming: In KMP modules, T383838commonMain and platform source sets (T383838androidMain, T383838jvmMain) share the same package namespace. If both contain a file with the same name (e.g., T383838LogExporter.kt), the Kotlin/JVM compiler will produce a duplicate class error. Use distinct filenames: keep the T383838expect declaration in T383838LogExporter.kt and put shared helpers in a separate file like T383838LogFormatter.kt.
β€’ Concurrency: Use Kotlin Coroutines and Flow.
β€’ Dependency Injection: Use Koin Annotations with the K2 compiler plugin (T383838koin-plugin in version catalog). The T383838koin-annotations library version is unified with T383838koin-core (both use T383838version.ref = "koin"). The T383838KoinConventionPlugin uses the typed T383838KoinGradleExtension to configure the K2 plugin (e.g., T383838compileSafety.set(false)). Keep root graph assembly in T383838app.
β€’ ViewModels: Follow the MVI/UDF pattern. Use the multiplatform T383838androidx.lifecycle.ViewModel in T383838commonMain.
β€’ BLE: All Bluetooth communication must route through T383838core:ble using Kable.
β€’ Networking: Pure Ktor β€” no OkHttp anywhere. Engines: T383838ktor-client-android for Android, T383838ktor-client-java for desktop/JVM. Use Ktor T383838Logging plugin for HTTP debug logging (not OkHttp interceptors). T383838HttpClient is provided via Koin in T383838app/di/NetworkModule and T383838core:network/di/CoreNetworkAndroidModule.
β€’ Image Loading (Coil): Use T383838coil-network-ktor3 with T383838KtorNetworkFetcherFactory on all platforms. T383838ImageLoader is configured in host modules only (T383838app via Koin T383838@Single, T383838desktop via T383838setSingletonImageLoaderFactory). Feature modules depend only on T383838libs.coil (coil-compose) for T383838AsyncImage β€” never add T383838coil-network-* or T383838coil-svg to feature modules.
β€’ Dependencies: Check T383838gradle/libs.versions.toml before assuming a library is available.
β€’ JetBrains fork aliases: Version catalog aliases for JetBrains-forked AndroidX artifacts use the T383838jetbrains-* prefix (e.g., T383838jetbrains-lifecycle-runtime-compose, T383838jetbrains-navigation3-ui). Plain T383838androidx-* aliases are true Google AndroidX artifacts. Never mix them up in T383838commonMain.
β€’ Compose Multiplatform: Version catalog aliases for Compose Multiplatform artifacts use the T383838compose-multiplatform-* prefix (e.g., T383838compose-multiplatform-material3, T383838compose-multiplatform-foundation). Never use plain T383838androidx.compose dependencies in common Main.
β€’ Room KMP: Always use T383838factory = { MeshtasticDatabaseConstructor.initialize() } in T383838Room.databaseBuilder and T383838inMemoryDatabaseBuilder. DAOs and Entities reside in T383838commonMain.
β€’ QR Codes: Use T383838rememberQrCodePainter from T383838core:ui/commonMain (powered by T383838qrcode-kotlin) for generating QR codes. Do not use Android Bitmap or ZXing APIs in common code.
β€’ Testing: Write ViewModel and business logic tests in T383838commonTest. Use T383838Turbine for Flow testing, T383838Kotest for property-based testing, and T383838Mokkery for mocking. Use T383838core:testing shared fakes.
β€’ Build-logic conventions: In T383838build-logic/convention, prefer lazy Gradle configuration (T383838configureEach, T383838withPlugin, provider APIs). Avoid T383838afterEvaluate in convention plugins unless there is no viable lazy alternative.

C. Namespacing
β€’ Standard: Use the T383838org.meshtastic.* namespace for all code.
β€’ Legacy: Maintain the T383838com.geeksville.mesh Application ID.

4. Execution Protocol

A. Environment Setup
1. JDK 17 MUST be used to prevent Gradle sync/build failures.
2. Secrets: You must copy T383838secrets.defaults.properties to T383838local.properties:
T282828
Te6edf3MAPS_API_KEYTff7b72=Ta5d6ffdummy_key
Te6edf3datadogApplicationIdTff7b72=Ta5d6ffdummy_id
Te6edf3datadogClientTokenTff7b72=Ta5d6ffdummy_token


B. Strict Execution Commands
Always run commands in the following order to ensure reliability. Do not attempt to bypass T383838clean if you are facing build issues.

Baseline (recommended order):
T282828
./gradlew clean
./gradlew spotlessCheck
./gradlew spotlessApply
./gradlew detekt
./gradlew assembleDebug
./gradlew Tffa657test


Testing:
T282828
./gradlew Tffa657test T8b949e# Run local unit tests
./gradlew testFdroidDebugUnitTest testGoogleDebugUnitTest T8b949e# CI-aligned Android unit tests (flavor-explicit)
./gradlew connectedAndroidTest T8b949e# Run instrumented tests
./gradlew testFdroidDebug testGoogleDebug T8b949e# Flavor-specific unit tests
./gradlew lintFdroidDebug lintGoogleDebug T8b949e# Flavor-specific lint checks

Note: If testing Compose UI on the JVM (Robolectric) with Java 17, pin your tests to T383838@Config(sdk = [34]) to avoid SDK 35 compatibility crashes.

CI workflow conventions (GitHub Actions):
β€’ Reusable CI is split into a host job and an Android matrix job in T383838.github/workflows/reusable-check.yml.
β€’ Host job runs style/static checks, explicit Android lint tasks, unit tests, and Kover XML coverage uploads once.
β€’ Android matrix job runs explicit assemble tasks for T383838app and T383838mesh_service_example; instrumentation is enabled by input and matrix API.
β€’ Prefer explicit Gradle task paths in CI (for example T383838app:lintFdroidDebug, T383838app:connectedGoogleDebugAndroidTest) instead of shorthand tasks like T383838lintDebug.
β€’ Pull request CI is main-only (T383838.github/workflows/pull-request.yml targets T383838main branch).
β€’ Gradle cache writes are trusted on T383838main and merge queue runs (T383838merge_group / T383838gh-readonly-queue/*); other refs use read-only cache mode in reusable CI.
β€’ PR T383838check-changes path filtering lives in T383838.github/workflows/pull-request.yml and must include module dirs plus build/workflow entrypoints (T383838build-logic/**, T383838gradle/**, T383838.github/workflows/**, T383838gradlew, T383838settings.gradle.kts, etc.) so CI is not skipped for infra-only changes.

C. Documentation Sync
Update documentation continuously as part of the same change. If you modify architecture, module targets, CI tasks, validation commands, or agent workflow rules, update the relevant docs (T383838AGENTS.md, T383838.github/copilot-instructions.md, T383838GEMINI.md, T383838docs/agent-playbooks/*, T383838docs/kmp-status.md, and T383838docs/decisions/architecture-review-2026-03.md).

5. Troubleshooting
β€’ Build Failures: Check T383838gradle/libs.versions.toml for dependency conflicts.
β€’ Missing Secrets: Check T383838local.properties.
β€’ JDK Version: JDK 17 is required.
β€’ Configuration Cache: Add T383838--no-configuration-cache flag if cache-related issues persist.
β€’ Koin Injection Failures: Verify the KMP component is included in T383838app root module wiring (T383838AppKoinModule).

Served by rngit 1.5.2 - Generated in 0.07s